/*
 * ==============================================================================
 * ||                    TikTok API 响应“安全提取”脚本                          ||
 * ==============================================================================
 *
 * 策略:
 * 1. 确认 LIZLLL 被调用，说明 SSL Pinning 已绕过。
 * 2. 认识到 gson.toJson() 会因混淆导致崩溃。
 * 3. 放弃 Gson，使用手动、安全的 Java 反射来逐个打印 responseBody 的字段。
 *    这是查看混淆对象内部最安全、最可靠的方法。
 *
 */

console.log("====== “安全提取”脚本已部署，准备进行最终捕获... ======");

Java.perform(function() {
    console.log("====== Java.perform() 已执行，Hook 已就位。 ======");

    const SsResponse = Java.use("X.DBo");

    // 一个辅助函数，用于安全地、递归地打印一个对象的内部字段
    function safeInspectObject(obj, indent = "  ") {
        if (!obj) {
            console.log(indent + "Object is null");
            return;
        }

        try {
            const javaClass = obj.getClass();
            const fields = javaClass.getDeclaredFields();
            
            console.log(indent + "Inspecting object of class: " + javaClass.getName() + ` (has ${fields.length} fields)`);

            fields.forEach(function(field) {
                // 强制访问私有字段
                field.setAccessible(true);
                const fieldName = field.getName();
                let fieldValue;
                try {
                    fieldValue = field.get(obj);
                } catch (e) {
                    fieldValue = "[Error getting value]";
                }
                
                // 打印字段名和值
                console.log(indent + `|-- Field: ${fieldName}, Value: ${fieldValue}`);

                // 如果字段值是另一个复杂对象，并且我们还没有深入太多层，就递归检查
                if (indent.length < 10 && fieldValue && fieldValue.getClass && !fieldValue.getClass().isPrimitive() && !fieldValue.getClass().getName().startsWith("java.lang")) {
                    safeInspectObject(fieldValue, indent + "  ");
                }
            });
        } catch (e) {
            console.log(indent + "[Error inspecting object: " + e.message + "]");
            // 如果反射失败，就回退到 toString()
            console.log(indent + "Fallback to .toString(): " + obj.toString());
        }
    }


    // Hook 创建成功响应的静态工厂方法
    SsResponse.LIZLLL.implementation = function(responseBody, rawResponse) {
        
        const result = this.LIZLLL(responseBody, rawResponse);

        try {
            let url = "[URL not found or failed to read]";
            if (rawResponse && rawResponse.LIZ && rawResponse.LIZ.value) {
                url = rawResponse.LIZ.value;
            }
            
            // 为了避免错过任何东西，我们先不过滤，全部打印
            console.log("\n\n\n" + "======================================================");
            console.log("             >>> API Response Intercepted <<<             ");
            console.log("------------------------------------------------------");
            console.log("[*] URL: " + url);
            console.log("------------------------------------------------------");

            if (responseBody) {
                console.log("[+] Inspecting Response Body safely...");
                // 使用我们自定义的安全检查函数，而不是 gson.toJson()
                safeInspectObject(responseBody);
            } else {
                console.log("[-] Response Body is null.");
            }
            console.log("========================================================\n\n\n");

        } catch (e) {
            console.error("[!] Hook 逻辑执行出错: " + e);
        }

        return result;
    };

    console.log("[*] 安全 Hook 已激活: X.DBo.LIZLLL");
    console.log("[*] 正在监听所有成功的网络请求... 请在 App 中操作。");
});





// /*
//  * 调试脚本：暴力打印 rawResponse 对象的内部结构，以找到 URL 的真实位置。
//  */

// console.log("====== 调试脚本已启动，准备寻找 URL 的藏身之处... ======");

// Java.perform(function() {
//     console.log("====== Java.perform() 已调用，准备 hook。 ======");

//     const SsResponse = Java.use("X.DBo");

//     // 一个计数器，避免打印过多日志，只看前几次调用即可
//     let callCount = 0;
//     const maxCallsToInspect = 30; // 检查前10次调用

//     SsResponse.LIZLLL.implementation = function(responseBody, rawResponse) {
//         const result = this.LIZLLL(responseBody, rawResponse);

//         // 只检查前几次调用，避免日志刷屏
//         if (callCount < maxCallsToInspect) {
//             try {
//                 console.log("\n\n" + `=============== Inspecting Call #${callCount + 1} ===============`);
                
//                 if (rawResponse) {
//                     console.log("[*] rawResponse object found. Type: " + rawResponse.$className);

//                     // 获取 rawResponse 对象的所有字段
//                     const fields = rawResponse.getClass().getDeclaredFields();
//                     console.log(`[*] It has ${fields.length} fields. Let's inspect them:`);

//                     // 遍历所有字段
//                     fields.forEach(function(field) {
//                         field.setAccessible(true); // 允许访问私有字段
//                         const fieldName = field.getName();
//                         let fieldValue;
//                         try {
//                             // 获取字段的值
//                             fieldValue = field.get(rawResponse);
//                         } catch (e) {
//                             fieldValue = "Error getting value: " + e.message;
//                         }
                        
//                         // 打印字段名和字段值
//                         console.log(`  |-- Field: ${fieldName}, Value: ${fieldValue}`);

//                         // 尝试进一步探索，如果字段值是对象，看看它内部有什么
//                         if (fieldValue && fieldValue.toString().includes('@')) { // 简单的对象判断
//                              try {
//                                 const innerFields = fieldValue.getClass().getDeclaredFields();
//                                 innerFields.forEach(function(innerField) {
//                                     innerField.setAccessible(true);
//                                     const innerFieldName = innerField.getName();
//                                     const innerFieldValue = innerField.get(fieldValue);
//                                     console.log(`  |    |-- Inner Field: ${innerFieldName}, Value: ${innerFieldValue}`);
//                                 });
//                              } catch(e) {}
//                         }
//                     });

//                 } else {
//                     console.log("[*] rawResponse object is null.");
//                 }
//                 console.log(`====================================================\n`);

//             } catch (e) {
//                 console.error("[!] Error during inspection: " + e);
//             }
//             callCount++;
//         }

//         return result;
//     };

//     console.log("[+] Debug hook on 'X.DBo.LIZLLL' is active. Watching for the first few calls...");
// });